<template>
  <van-pull-refresh v-model="state.refreshing" @refresh="handlerRefresh">
    <van-list v-model:loading="state.loading" v-model:error="state.error" :error-text="errorText"
              :finished="state.finished" :finished-text="finishedText" @load="handlerLoad">
      <slot></slot>
    </van-list>
  </van-pull-refresh>
</template>

<script setup lang="ts">
import {onActivated, reactive, ref} from 'vue';
import {onBeforeRouteLeave, useRoute} from 'vue-router';

const route = useRoute()

interface propsType {
  modelValue: any[]
  pageSize?: number // 分页大小
  finishedText?: string // 结束时候文案
  errorText?: string // 失败时候文案
  needPaging?: boolean //是否需要分页
}

const props = withDefaults(
    defineProps<propsType>(), {
      pageSize: 10,
      finishedText: '没有更多了~',
      errorText: '加载失败了~',
      needPaging: true
    })

const emit = defineEmits(['onLoad', 'update:modelValue'])

const state = reactive({
  loading: false,
  error: false,
  finished: false,
  refreshing: false,
  pageNo: 1,
})

// 下拉刷新
const handlerRefresh = () => {
  // 清空列表数据
  state.finished = false;

  // 重新加载数据
  // 将 loading 设置为 true，表示处于加载状态
  // state.loading = true
  handlerLoad(true)
};

// 滚动加载
const handlerLoad = (refreshing = false) => {
  // console.log(`滚动加载:当前第${state.pageNo}页`)
  if (refreshing) {
    state.pageNo = 1
    emit('update:modelValue', props.modelValue.splice(0, props.modelValue.length, ...[]));
    emit('onLoad', {pageNo: 1, pageSize: props.pageSize})
  } else {
    emit('onLoad', {pageNo: state.pageNo, pageSize: props.pageSize})
  }
};

// 数据处理方法：外部直接调用
/**
 * 使用方法
 * 1.ref.value.complate(false) 表示加载错误
 * 2.ref.value.complate({分页接口返回的result对象}) + needPaging设置为true 表示自动处理数据
 * 3.ref.value.complate({不分页接口返回的result对象}) + needPaging设置为false 表示不需要分页，并且自动处理数据
 */
const complate = (e: any) => {
  // 需要分页
  if (props.needPaging) {
    dealPaging(e)
  } else {
    dealNoPaging(e)
  }

  if (state.refreshing === true) {
    state.refreshing = false
  }
  state.loading = false
}

// 处理分页
const dealPaging = (e: Record<string, any>) => {
  if (Array.isArray(e.records)) {
    state.pageNo = e.current
    if (state.pageNo == 1) {
      emit('update:modelValue', [...e.records]);
      // 滚动到顶部
      setTimeout(() => {
        document.documentElement.scrollTop = 0
      })
    } else {
      emit('update:modelValue', [...props.modelValue, ...e.records]);
    }
    // list状态处理
    dealState(e)
  } else {
    // 如果返回的是布尔值 false表示报错了
    state.error = true
  }
}

// 处理不需要分页
const dealNoPaging = (e: any[]) => {
  if (Array.isArray(e)) {
    emit('update:modelValue', [...e]);
    // 滚动到顶部
    setTimeout(() => {
      document.documentElement.scrollTop = 0
    })
    // list状态处理
    dealState(e)
  } else {
    // 如果返回的是布尔值 false表示报错了
    state.error = true
  }
}

// 处理列表状态
const dealState = (e: Record<string, any>) => {
  // 不需要分页,直接设为列表加载结束
  if (!props.needPaging) {
    return state.finished = true
  }
  // 如果需要分页,就继续执行下面的
  if (e.records.length < props.pageSize) {
    // 如果返回的列表数据 小于pageSize,说明没有下一页了
    state.finished = true
  } else {
    state.pageNo++
    state.finished = false
  }
}

defineExpose({
  complate
})

// 记录时间戳
const isActive = ref('')

onActivated(() => {
  if (route.query.timeStr !== isActive.value) {
    // console.log('刷新列表')
    // 如果时间戳不一样,表示需要刷新列表,滚动到顶部
    // van-list组件会自动触发加载的方法,不需要手动触发
    isActive.value = route.query.timeStr as string
    localStorage.removeItem('scrollTop')
  } else {
    // console.log('滚动位置要复位')
    // 如果时间戳一样,表示不需要刷新列表,但是滚动位置要复位
    // 如果是页面级的滚动,滚动的对象是documentElement
    // 如果是固定高度的盒子进行滚动,滚动对象是盒子
    // 暂时先用页面级滚动吧
    setTimeout(() => {
      document.documentElement.scrollTop = Number(localStorage.getItem('scrollTop'))
    })
  }
})

onBeforeRouteLeave(() => {
  let scrollTop = document.documentElement.scrollTop;
  // console.log('scrollTop==', scrollTop)
  localStorage.setItem('scrollTop', scrollTop.toString())
})
</script>